<div id="app">
  {{title}}
</div>
​

<script>
  const Vue={
    createApp(options){
      // 返回app实例
      return{
        mount(seletor){
          console.log("mount!")
          // 1.找到宿主元素
          const parent=document.querySelector(seletor)
          // 2.渲染页面
          // 2.1 处理template：编译
          if(!options.render){
            options.render=this.compile(parent.innerHTML)
          }
          // 2.2 用户直接编写render
          // ctx把data返回值作为上下文




          if(options.setup){
            this.setupState=options.setup();
          }
          if(options.data){
            this.data=options.data();
          }

          // setup和其他选项做兼容
          const proxy=new Proxy(this,{
            get(target,key) {
              // 先从setup中取，再到data中取
              if(target.setupState&&key in target.setupState){
                return target.setupState[key]
              }else{
                return target.data[key]
              }
            },
            set(target,key,val) {
              // 先从setup中取，再到data中取
              if(target.setupState&&key in target.setupState){
                target.setupState[key]=val
              }else{
                target.data[key]=val;
                
              }
            },
          })



          this.update=function(){
            // const el=options.render.call(options.data())
            const el=options.render.call(proxy)   //兼容性


            // 3.追加到宿主
            parent.innerHTML=''
            insert(el,parent)


          }
          this.update()
          
          




          parent.appendChild(el)

        },
        compile(template){
          // 返回一个render函数
          // parser->ast
          // generate->ast=>render
          return function render(){
            const h3=document.createElement('h3')
            h3.textContent=this.title
            return h3
          }
        }
      }
    }
  }
</script>


<script>
// 能够拦截用户对代理对象的访问，
// 从而能在值发生变化时做出响应式
function reactive(obj){
  // vue2
  // Object.defineProperties(obj,{})
  // 缺点：
  // 1.vue2需要递归，效率问题
  // 2.数组解决不了调用的拦截，需要一套单独实现方案
  // 3.api
  // 4.数据结构问题

  // 拦截
  new Proxy(obj,{
    get(target,key){
      console.log("get key:",key)
      // Reflect 跟proxy一模一样的方法
   
      return target[key]
    },
    set(target,key,val){
      console.log("set key:",key)
      target[key]=val
      // 通知更新
      app.update()
    }
  })
}



const app = Vue.createApp({
  setup(){
    // 实现一个响应式reactive,同时设立拦截，建立更新机制
    // create
    const state=reactive({
      title:'vue3,hello!---setup'
    })
    setTimeout(()=>{
      state.title='hello vue3333333333333'
    },2000)
    return state
  }
})

app.mount('#app')
</script>